package com.gitee.zycra.future.job.dao;

import com.gitee.zycra.future.job.common.bo.JobTriggerBO;
import com.gitee.zycra.future.job.common.bo.PageQuery;
import com.gitee.zycra.future.job.common.model.JobRunning;
import com.gitee.zycra.future.job.common.param.PageQueryRunningParam;
import com.gitee.zycra.jdbc.common.BaseDao;
import com.gitee.zycra.jdbc.common.CommonSelector;
import com.gitee.zycra.jdbc.enums.SQLConditionEnum;
import com.gitee.zycra.jdbc.enums.SQLLinkEnum;
import com.gitee.zycra.jdbc.model.PageQueryWrapper;
import com.gitee.zycra.jdbc.model.PageResult;
import com.gitee.zycra.jdbc.util.SQLBlock;
import com.gitee.zycra.jdbc.util.SQLChain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @author zycra
 */
@Repository
public class JobRunningDao extends BaseDao<JobRunning> {

    @Autowired
    private CommonSelector commonSelector;

    /**
     * 插入任务信息
     *
     * @param jobRunning 任务信息对象
     * @return 插入条数
     */
    public int insertJobRunning(JobRunning jobRunning) {
        return insertIntoTable(jobRunning, false);
    }

    /**
     * 根据主键查询任务信息
     *
     * @param id 主键
     * @return 任务信息
     */
    public JobRunning selectById(Long id) {
        return selectTableById(new JobRunning().setId(id));
    }

    /**
     * 根据任务调度ID查询
     *
     * @param pageQuery 查询参数
     * @return 查询到的数据
     */
    public PageResult<JobRunning> selectJobRunning(PageQuery<PageQueryRunningParam> pageQuery) {
        PageQueryRunningParam queryParam = pageQuery.getParam();
        SQLChain sqlChain = SQLChain.builder()
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "job_name", SQLConditionEnum.CONTAINS, queryParam.getJobName()))
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "schedule_name", SQLConditionEnum.CONTAINS, queryParam.getScheduleName()))
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "schedule_time", SQLConditionEnum.GREATER_OR_EQUALS_THAN,
                        queryParam.getScheduleTimeStart()))
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "schedule_time", SQLConditionEnum.LESS_THAN, queryParam.getScheduleTimeEnd()))
                .build();
        PageQueryWrapper param = new PageQueryWrapper(getCountSqlWithOutParam() + sqlChain.getSQL(),
                sqlChain.getParamList(), getSelectAllColumnSql() + sqlChain.getSQL() + " ORDER BY schedule_time DESC",
                sqlChain.getParamList(), pageQuery.getPage(), pageQuery.getSize());
        return selectTableForPage(param);
    }

    /**
     * 查询待调度任务
     *
     * @return 待调度任务
     */
    public List<JobTriggerBO> selectJobForTrigger() {
        return commonSelector.selectByParam(getJdbcTemplate(),
                "SELECT id, job_schedule_id, schedule_param, schedule_time, job_class_name, application_name, node_ip, schedule_ratio FROM "
                        + "job_running WHERE schedule_time < DATE_ADD(NOW(), INTERVAL 1 MINUTE) AND schedule_ratio IN(0, -3, -4) "
                        + "AND node_ip IS NOT NULL",
                JobTriggerBO.class, null, false);
    }

    /**
     * 根据ID更新
     *
     * @param jobRunning 执行信息
     * @return 更新条数
     */
    public int updateJobRunning(JobRunning jobRunning) {
        return updateTableById(jobRunning, false);
    }

    /**
     * 查询待转移的任务
     *
     * @return 待转移的任务
     */
    public List<JobRunning> selectForTransfer() {
        return commonSelector.selectByParam(getJdbcTemplate(),
                "SELECT * FROM job_running WHERE complete_time IS NOT NULL", JobRunning.class, null, false);
    }

    /**
     * 根据调度ID查询
     *
     * @param jobScheduleId 调度ID
     * @return 执行信息
     */
    public JobRunning selectByJobScheduleId(Long jobScheduleId) {
        return selectOneTableByNotNullColumnEquals(new JobRunning().setJobScheduleId(jobScheduleId));
    }

    /**
     * 根据ID删除
     *
     * @param idList id集合
     * @return 删除行数
     */
    public int deleteRunning(List<Long> idList) {
        SQLChain sqlChain = SQLChain.builder()
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "id", SQLConditionEnum.IN, idList.toArray()))
                .build();
        return getJdbcTemplate().update("DELETE FROM job_running" + sqlChain.getSQL(), sqlChain.getParamList().toArray());
    }

    /**
     * 检查超时任务
     *
     * @return 影响行数
     */
    public int checkTimeoutAndUpdate() {
        return getJdbcTemplate().update("UPDATE job_running SET schedule_ratio = -4, complete_time = NOW() WHERE complete_time IS NULL AND "
                + "timeout_time < NOW()");
    }
}
